package pl.edu.agh.persdoc;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Component;

import com.googlecode.charts4j.AxisLabels;
import com.googlecode.charts4j.AxisLabelsFactory;
import static com.googlecode.charts4j.Color.*;

import com.googlecode.charts4j.AxisStyle;
import com.googlecode.charts4j.AxisTextAlignment;
import com.googlecode.charts4j.Color;
import com.googlecode.charts4j.Data;
import com.googlecode.charts4j.DataUtil;
import com.googlecode.charts4j.Fills;
import com.googlecode.charts4j.GCharts;
import com.googlecode.charts4j.Line;
import com.googlecode.charts4j.LineChart;
import com.googlecode.charts4j.LineStyle;
import com.googlecode.charts4j.Plot;
import com.googlecode.charts4j.Plots;
import com.googlecode.charts4j.Shape;

import pl.edu.agh.persdoc.model.Examination;

/**
 * Class responsible for processing examination results data in order to prepare
 * appropriate graphs for displaying them
 * @author lewickitom
 *
 */
@Component
public class ExaminationsProcessor {

	
	/**
	 * Creates url that represents Google Charts that visualize examination results for a given patient. 
	 * @param list - contains all saved examinations data for a given patient 
	 * @return - map with key-value pairs each representing type of examination and url for displaying results
	 * of this examination (url for Google Charts API)
	 */
	public Map<String,String> createGraphsForPatient(List<Examination> list) {
		
		Series series=extractDataSeries(list);
		Map<String,String> results=new HashMap<String, String>();
		for(String name:series.dataSeries.keySet()){
			results.put(name, createGraphForDataSeries(series.dataSeries.get(name),series.timeSeries.get(name)));
		}
		return results;
	}
	
	
	private Series extractDataSeries(List<Examination> examinations){
			
		Map<String,List<Examination>> examSeries=getExaminationsGroupedByNames(examinations);
		sortExaminationsByTimestamp(examSeries);
		
		Map<String,List<Double>> dataSeries =new HashMap<String,List<Double>>();		
		Map<String,List<String>> timeSeries =new HashMap<String,List<String>>();		
		DateFormat df=DateFormat.getDateTimeInstance();
		for(String examName:examSeries.keySet()){
			List<Double> data=new ArrayList<Double>();
			List<String> time=new ArrayList<String>();
			for(Examination e:examSeries.get(examName)){
				double d=e.getValue();
				data.add(d);
				time.add(df.format(e.getTimestamp()));
			}
			dataSeries.put(examName, data);
			timeSeries.put(examName, time);
		}
		return new Series(dataSeries,timeSeries);
	}



	private void sortExaminationsByTimestamp(
			Map<String, List<Examination>> examSeries) {
		for(List<Examination> list:examSeries.values()){
			Collections.sort(list,new Comparator<Examination>(){
				@Override
				public int compare(Examination arg0, Examination arg1) {
					return arg0.getTimestamp().compareTo(arg1.getTimestamp());
				}		
			});	
			System.out.println("\nSORTED LIST");
			for(Examination e:list){
				System.out.println(DateFormat.getInstance().format(e.getTimestamp())+"  ,  ");
				
			}
		}
	}



	private Map<String, List<Examination>> getExaminationsGroupedByNames(List<Examination> examinations) {
		Map<String,List<Examination>> examSeries =new HashMap<String,List<Examination>>();
		for(Examination exam: examinations){
			
			String examName= exam.getName();
			if(!examSeries.containsKey(examName)){
				List<Examination> list=new ArrayList<Examination>();
				list.add(exam);
				examSeries.put(examName, list);
			}
			else{
				examSeries.get(examName).add(exam);
			}
			
		}
		return examSeries;
	}
	
	private String createGraphForDataSeries(List<Double> dataSerie,List<String> timeSerie) {
		
	    // EXAMPLE CODE START
	    // Defining Line
		System.out.println("\n\nDATA SERIE  "+dataSerie);

	    Line line1 = Plots.newLine(DataUtil.scaleWithinRange(0,getMaxFromList(dataSerie),dataSerie), YELLOW);
	    line1.setLineStyle(LineStyle.newLineStyle(3, 1, 0));
	    line1.addShapeMarkers(Shape.CIRCLE, YELLOW, 10);
	    line1.addShapeMarkers(Shape.CIRCLE, BLACK, 7);
	//    line1.setFillAreaColor(LIGHTYELLOW);

	  
	    // Defining chart.
	    LineChart chart = GCharts.newLineChart(line1);
	    chart.setSize(600, 450);
	 //   chart.setTitle("S & P 500|1962 - 2008", WHITE, 14);

	    // Defining axis info and styles
	    AxisStyle axisStyle = AxisStyle.newAxisStyle(WHITE, 12, AxisTextAlignment.CENTER);
	    AxisLabels yAxis = AxisLabelsFactory.newNumericRangeAxisLabels(0, getMaxFromList(dataSerie));
	    yAxis.setAxisStyle(axisStyle);
//	    AxisLabels xAxis2 = AxisLabelsFactory.newNumericRangeAxisLabels(1962, 2008);
//	    xAxis2.setAxisStyle(axisStyle);
	    AxisLabels xAxis3 = AxisLabelsFactory.newAxisLabels(timeSerie);
	    xAxis3.setAxisStyle(AxisStyle.newAxisStyle(WHITE, 10, AxisTextAlignment.CENTER));
	    
	    // Adding axis info to chart.
	    chart.addYAxisLabels(yAxis);
	    chart.addXAxisLabels(xAxis3);
	    chart.setGrid(100, 1, 5, 0);

	    // Defining background and chart fills.
	    chart.setBackgroundFill(Fills.newSolidFill(Color.newColor("406C93")));
	    chart.setAreaFill(Fills.newSolidFill(Color.newColor("708090")));
	    chart.setMargins(20, 20, 20, 20);
	    String url = chart.toURLString();

	    return url;
	}
	
	private double getMaxFromList(List<Double>  list){
		double max = list.get(0);
		for (int i=1; i<list.size(); i++){
		  if (list.get(i)>max){
		    max = list.get(i);
		  }
		}
		return max;
	}
	
	class Series{
		public Map<String,List<Double>> dataSeries;
		public Map<String,List<String>> timeSeries;
		public Series(Map<String, List<Double>> dataSeries, Map<String, List<String>> timeSeries){
			this.dataSeries=dataSeries;
			this.timeSeries=timeSeries;
		}
		
	}
	

	
}


